package com.example.demo.thread.ch5;

import com.example.demo.thread.util.Debug;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 通用的线程优雅停止办法实例
 *
 * @author: htc
 * @date: Created in 17:02 2019/1/14.
 */
public class TerminatableTaskRunner implements TaskRunnerSpec{
    protected final BlockingQueue<Runnable> channel;
    //线程停止标记
    protected volatile boolean inUse = true;
    //待处理任务计数器(使用原子变量表示待处理任务的数量，即传输通道中任务的数量)
    public final AtomicInteger reservations = new AtomicInteger(0);

    private volatile Thread workerThread;

    public TerminatableTaskRunner(BlockingQueue<Runnable> channel) {
        this.channel = channel;
        this.workerThread = new WorkerThread();
    }

    public TerminatableTaskRunner() {
        this(new LinkedBlockingDeque<Runnable>());
    }

    @Override
    public void init() {
        final Thread t  = workerThread;
        if (null != t){
            t.start();
        }
    }

    @Override
    public void submit(Runnable task) throws InterruptedException {
        channel.put(task);
        //语句1
        reservations.incrementAndGet();
    }

    public void shutdown(){
        Debug.info("Shutting down service...");
        //语句2
        inUse = false;
        final Thread t = workerThread;
        if (null != t){
            //语句3
            t.interrupt();
        }
    }

    public void cancelTask(){
        Debug.info("Canceling in progress task...");
        workerThread.interrupt();
    }

    class WorkerThread extends Thread {
        @Override
        public void run() {
            Runnable task = null;
            try {
                for (; ; ) {
                    //线程不再被需要，且无待处理任务
                    //语句4
                    if (!inUse && reservations.get() <= 0) {
                        break;
                    }
                    task = channel.take();
                    try {
                        task.run();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    //使待处理任务数减少1
                    //语句5
                    reservations.decrementAndGet();
                }
            } catch (InterruptedException e) {
                Debug.info("worker thread terminated.");
            }
        }
    }
}
